﻿using AutoMapper;
using ManagementApi.Models;
using ManagementApi.Models.Device;
using ManagementApi.Models.Person;
using ManagementApi.Mvc;
using ManagementApi.Mvc.ApplicationContexts;
using ManagementApi.TreeParty.SMS.LianXinTong;
using Microsoft.AspNetCore.Mvc;
using Modules;
using Modules.Base;
using Modules.CheckIn;
using Modules.CheckIn.Entitys;
using Modules.Device;
using Modules.Device.Entitys;
using Modules.FaceScan;
using Modules.FaceScan.Entitys;
using Modules.Person;
using Modules.Project;
using Modules.Project.Entitys;
using Modules.SMS;
using Modules.SMS.Entitys;
using Org.BouncyCastle.Utilities.Encoders;
using PmSoft.FileStorage;
using PmSoft.Utilities;
using static Modules.CheckIn.CheckInDetailConstants;
using static Modules.Device.CheckInDeviceConstants;
using static Modules.Person.PersonConstants;

namespace ManagementApi.Controllers
{
    /// <summary>
    /// 开放接口
    /// </summary>
    [Route("/api")]
    [ApiController]
    public class OpenApiController : ControllerBase
    {
        private readonly FacePhotoService personFaceService;
        private readonly IFileStorage fileStorage;
        private readonly FaceScanRecordService faceScanRecordService;
        private readonly PersonService personService;
        private readonly CheckinDeviceService projectCheckinDeviceService;
        private readonly IMapper mapper;
        private readonly ManagementApplicationContext applicationContext;
        private readonly CheckInDetailService checkInDetailService;
        private readonly ProjectGroupMemberService projectGroupMemberService;
        private readonly CheckinDeviceCommandService projectCheckinDeviceCommandLogService;
        private readonly SmsSendLogService smsSendLogService;
        private readonly ILogger logger;

        public OpenApiController(FacePhotoService personFaceService, IFileStorage fileStorage, PersonService personService, IMapper mapper, FaceScanRecordService faceScanRecordService, ManagementApplicationContext applicationContext, CheckinDeviceService projectCheckinDeviceService, CheckInDetailService checkInDetailService, ProjectGroupMemberService projectGroupMemberService, CheckinDeviceCommandService projectCheckinDeviceCommandLogService, SmsSendLogService smsSendLogService, ILogger<OpenApiController> logger)
        {
            this.personFaceService = personFaceService;
            this.fileStorage = fileStorage;
            this.mapper = mapper;
            this.faceScanRecordService = faceScanRecordService;
            this.personService = personService;
            this.applicationContext = applicationContext;
            this.projectCheckinDeviceService = projectCheckinDeviceService;
            this.checkInDetailService = checkInDetailService;
            this.projectGroupMemberService = projectGroupMemberService;
            this.projectCheckinDeviceCommandLogService = projectCheckinDeviceCommandLogService;
            this.smsSendLogService = smsSendLogService;
            this.logger = logger;
        }

        #region 身份证阅读器数据 (来自身份证阅读器守护程序)

        /// <summary>
        /// 根据身份证查询认证记录
        /// </summary>
        /// <param name="idCard"></param>
        /// <returns></returns>
        [HttpGet("GetPersonFace")]
        public ApiResult<PersonFaceDto> GetPersonFace(string idCard)
        {
            logger.LogInformation($"实名制平台接收到参数:{idCard}");
            PersonInfo? personInfo = personService.GetPersonByCardNo(idCard);
            if (personInfo == null)
                return ApiResult<PersonFaceDto>.Failure("没查询到数据");
            FacePhoto? personFace = personFaceService.GetPersonFaceByIdCard(idCard);
            if (personFace == null)
                return ApiResult<PersonFaceDto>.Failure("没查询到数据");
            PersonFaceDto personFaceDto = new PersonFaceDto();
            mapper.Map(personFace, personFaceDto);

            #region 获取流

            // 调用 GetObjectAsync 方法来获取对象的流
            byte[] objectData = personFaceService.GeVerifyPhotoData(idCard);
            if (objectData.Length > 0)
                personFaceDto.Base64PhotoStr = Base64.ToBase64String(objectData);
            personFaceDto.SecurityId = personInfo.SecurityId == null ? 0 : personInfo.SecurityId;

            #endregion 获取流

            return ApiResult<PersonFaceDto>.Success(personFaceDto);
        }

        /// <summary>
        /// 上传人脸识别记录
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        [HttpPost("ReportScan")]
        public async Task<ApiResult<int>> ReportScanAsync([FromBody] PersonFaceScanRecordEditForm form)
        {
            FaceScanRecord record = new FaceScanRecord();
            mapper.Map(form, record);
            faceScanRecordService.Create(record);

            #region 上传到minio

            if (!string.IsNullOrEmpty(form.Base64PhotoStr))
            {
                byte[] picData = Base64Utilities.ConverBase64(form.Base64PhotoStr);
                string objectName = form.CameraPhoto;
                await fileStorage.PutFileAsync(FileBuckets.Person, objectName, picData);
            }

            #endregion 上传到minio

            return ApiResult<int>.Success(record.Id);
        }

        #endregion 身份证阅读器数据 (来自身份证阅读器守护程序)

        #region 考勤机数据处理

        /// <summary>
        /// 设备上下线通知
        /// </summary>
        /// <param name="projectCheckInDeviceForm"></param>
        /// <returns></returns>
        [HttpPost("updateDeviceAsync")]
        public async Task<ApiResult> UpdateProjectCheckInDevice([FromBody] CheckInDeviceForm projectCheckInDeviceForm)
        {
            CheckinDevice? projectCheckinDevice = projectCheckinDeviceService.GetProjectCheckinDevice(projectCheckInDeviceForm.Code);
            if (projectCheckinDevice == null)
                return ApiResult.Failure($"设备编号{projectCheckInDeviceForm.Code}不存在,请先添加设备");
            projectCheckinDevice.IsOnline = projectCheckInDeviceForm.IsOnline;
            if (projectCheckinDevice.IsOnline)
            {
                projectCheckinDevice.IpAddress = projectCheckInDeviceForm.IpAddress;
                projectCheckinDevice.LastSyncTime = projectCheckInDeviceForm.LastSyncTime;
            }
            projectCheckinDeviceService.Update(projectCheckinDevice);
            return ApiResult.Success($"状态更新成功");
        }

        /// <summary>
        /// 认证识别结果推送
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        [HttpPost("RecPush")]
        public async Task<ApiResult> RecPush([FromBody] PersonFaceScanRecordEditForm form)
        {
            CheckinDevice? projectCheckinDevice = projectCheckinDeviceService.GetProjectCheckinDevice(form.DeviceCode);
            if (projectCheckinDevice == null)
                return ApiResult.Failure($"设备编号{form.DeviceCode}不存在,请先添加设备");
            PersonInfo? personInfo = personService.GetPersonByCardNo(form.IdCard);
            if (personInfo == null) return ApiResult.Failure("人员信息不存在");
            FaceScanRecord entity = new FaceScanRecord()
            {
                ReferType = FaceScanReferType.CheckIn,
                IdCard = form.IdCard,
                IsConfirmed = true,
                ConfirmTime = DateTime.Now,
                Similarity = form.Similarity,
                CreateTime = DateTime.Now,
                IsPassed = true,
                VerifyTime = DateTime.Now,
                CameraPhoto = $"{form.IdCard}/AttMachine_{form.IdCard}_{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.jpg",
                DataSource = 数据来源.考勤机
            };

            #region 上传到minio

            int base64Index = form.CameraPhoto.IndexOf("base64,");
            string substring = "";
            if (base64Index != -1)
                substring = form.CameraPhoto.Substring(base64Index + 7);
            byte[] picData = Base64Utilities.ConverBase64(substring.Trim());
            string objectName = entity.CameraPhoto;
            fileStorage.PutFileAsync(FileBuckets.Person, objectName, picData).GetAwaiter().GetResult();

            #endregion 上传到minio

            #region 新增考勤记录

            DateTime dateTime = DateTime.Now;
            进出标识 InOut = 进出标识.进场;
            考勤状态 Status = 考勤状态.有效;
            if (projectCheckinDevice.InOut == 进出.进)
                InOut = 进出标识.进场;
            else
                InOut = 进出标识.出场;
            //查询当前人员所在项目的班组
            var members = projectGroupMemberService.GetProjectGroupMembersByPersonId(personInfo.PersonId);
            List<ProjectGroupMember> projectGroupMembers = members.Where(a => a.ProjectId == projectCheckinDevice.ProjectId && a.Status == 进出场状态.进场).ToList();
            foreach (var projectGroupMember in projectGroupMembers)
            {
                CheckInDetail checkInDetail = new CheckInDetail()
                {
                    ProjectId = projectCheckinDevice.ProjectId,
                    MemberId = projectGroupMember.Id,
                    Status = Status,
                    EntryExitMark = InOut,
                    DataSources = 数据来源.考勤机,
                    CheckinDate = dateTime.Date,
                    CheckinTime = dateTime,
                    CreateTime = DateTime.Now,
                    PersonId = personInfo.PersonId,
                    GroupId = projectGroupMember.GroupId
                };
                checkInDetailService.Create(checkInDetail);
            }

            #endregion 新增考勤记录

            faceScanRecordService.Create(entity);
            return ApiResult.Success($"推送成功");
        }

        #endregion 考勤机数据处理

        #region 短信

        /// <summary>
        /// 上行短信接口通知
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost("/sms/deliver")]
        public ApiResult Deliver([FromBody] DELIVER_REQ request)
        {
            SmsSendLog smsSendLog = new SmsSendLog()
            {
                MsgId = request.ReqId,
                Phone = request.Mobile,
                MsgType = MsgType.RetrievePassword,
                MsgContent = request.Content,
                Status = 1,
                CreateTime = DateTime.Now,
                Extend1 = request.DestId
            };
            smsSendLogService.Create(smsSendLog);
            return ApiResult.Success($"上行短信接口通知成功");
        }

        #endregion 短信
    }
}